//new MVue({data:{...}})

class MVue {
  constructor(options) {
    this.$options = options;

    //数据响应化
    this.$data = options.data;
    this.observe(this.$data);
    //编译
    new Compile(options.el, this);

    //created执行
    if (options.created) {
      options.created.call(this)
    }
  }
  //对data数据遍历
  observe(value) {
    if (!value || typeof value !== 'object') {
      return;
    }
    //遍历该对象
    Object.keys(value).forEach(key => {
      this.defineReactive(value, key, value[key])
      //代理data中的属性到vue实例上
      this.proxyData(key)
    })
  }

  //数据响应化，对data数据绑定get和set
  defineReactive(obj, key, val) {
    this.observe(val);
    const dep = new Dep();
    Object.defineProperty(obj, key, {
      get() {
        Dep.target && dep.addDep(Dep.target)
        return val;
      },
      set(newVal) {
        if (val === newVal) {
          return;
        };
        val = newVal;
        dep.notify();
      }
    })
  }
  //因为我们操作的是this.加变量，
  //当我们执行this.name,就会触发
  //把新的this.name值赋给this.$data[name],同时触发this.$data[name]的get和set
  proxyData(key) {
    Object.defineProperty(this, key, {
      get() {
        return this.$data[key]
      },
      set(newVal) {
        this.$data[key] = newVal
      }
    })
  }
}

///Dep:用来管理Watcher
class Dep {
  constructor() {
    //这里存放若干依赖（watcher）
    this.deps = [];
  }
  addDep(dep) {
    this.deps.push(dep)
  }
  notify() {
    this.deps.forEach(dep => {
      dep.update()
    })
  }
}

//Watcher
class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm;
    this.key = key;
    this.cb = cb;
    //将当前Watcher实力指定到Dep静态属性target中
    Dep.target = this;
    //收集改变了的变量依赖
    this.vm[this.key];//触发getter，添加依赖，proxyData
    Dep.target = null
  }
  update() {
    this.cb.call(this.vm, this.vm[this.key])
  }
}